package com.qfedu.micrograss.grass.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qfedu.api.point.feign.PointFeignService;
import com.qfedu.common.baidu.info.CheckResult;
import com.qfedu.common.baidu.utils.BaiduTextCheckUtils;
import com.qfedu.common.core.common.PageVO;
import com.qfedu.common.core.common.R;
import com.qfedu.common.core.constants.CommonConstants;
import com.qfedu.common.core.entity.Grass;
import com.qfedu.common.core.entity.GrassLike;
import com.qfedu.common.core.utils.UserUtils;
import com.qfedu.common.redis.utils.RedisUtil;
import com.qfedu.micrograss.grass.mapper.GrassMapper;
import com.qfedu.micrograss.grass.param.GrassParam;
import com.qfedu.micrograss.grass.param.GrassSearchParam;
import com.qfedu.micrograss.grass.param.TodayLikeInfoParam;
import com.qfedu.micrograss.grass.service.GrassLikeService;
import com.qfedu.micrograss.grass.service.GrassService;
import com.qfedu.micrograss.grass.vo.GrassVO;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * @Classname GrassServiceImpl
 * @Description TODO
 * @Date 2025-05-28 11:09
 * @Created by 老任与码
 */
@Service
public class GrassServiceImpl implements GrassService {

    @Resource
    private GrassMapper grassMapper;

    @Resource
    private PointFeignService pointFeignService;

    @Resource
    private GrassLikeService grassLikeService;

    @Autowired
    private RedisUtil redisUtil;

    @Resource
    private ThreadPoolExecutor threadPoolExecutor;

    // 分布式事务的注解 ，AT模式
    @GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public void addGrass(GrassParam grassParam) {
        // 如果审核不合规，直接抛出异常
        // 根据实际业务，比如，自动审核返回疑似状态，考虑考虑将数据写入数据库，后台通过人工审核
        CheckResult checkResult = BaiduTextCheckUtils.textCheck(grassParam.getTitle() + grassParam.getContent());
        if (checkResult.getConclusionType() != 1) {
            throw new RuntimeException(checkResult.getMsg());
        }

        Integer uid = UserUtils.getUid();

        Grass grass = new Grass();
        BeanUtils.copyProperties(grassParam, grass);

        String imgPath = String.join(",", grassParam.getImgList());
        // String imgPath = grassParam.getImgList().stream().collect(Collectors.joining(","));
        grass.setImgPath(imgPath);
        grass.setUid(uid);
        grassMapper.insert(grass);

        // 送积分
        R r = pointFeignService.remoteAddPoint(2);
        if (r.getCode() == CommonConstants.FAIL) {
            // 抛异常

            // 也可以进行补偿处理
        }

        int a = 10 / 0;

    }

    @Override
    public PageVO<GrassVO> grassPage(GrassSearchParam grassSearchParam) {
        Integer uid = UserUtils.getUid();

        Page<Grass> page = new Page(grassSearchParam.getPageNum(), grassSearchParam.getPageSize());
        page = grassMapper.selectPage(page, Wrappers.lambdaQuery(Grass.class)
                .eq(Grass::getCheckStatus, 1));
        List<Grass> records = page.getRecords();

        // 查询登录用户，对应的文章的点赞记录
        List<Integer> idList = records.stream().map(grass -> grass.getId()).collect(Collectors.toList());
        List<GrassLike> grassLikes = grassLikeService.listByGrassIdsAndUid(idList, uid);

        String key = String.format("likeNum:%s", DateUtil.format(new Date(), "yyyyMMdd"));

        List<GrassVO> voList = records.stream().map(grass -> {
            GrassVO vo = new GrassVO();
            vo.setId(grass.getId());
            vo.setTitle(grass.getTitle());

            String[] split = grass.getImgPath().split(",");
            vo.setCoverImg(split[0]);

            // 数据表中存的不是最新数据，实时的点赞总数来自数据库表的likeNum字段和reids中当天点赞数
            Integer todayLikeNum = (Integer) redisUtil.getCacheMapValue(key, grass.getId().toString());
            vo.setLikeNum(todayLikeNum == null ? grass.getLikeNum() : grass.getLikeNum() + todayLikeNum);

            // 查询点赞记录中是否包含当前的文章id
            GrassLike findLike = grassLikes.stream().filter(grassLike -> grassLike.getGrassId().equals(grass.getId()))
                    .findFirst().orElse(null);
            vo.setLikeFlag(findLike == null ? 0 : 1);
            return vo;
        }).collect(Collectors.toList());

        PageVO<GrassVO> pageVO = new PageVO<>();
        pageVO.setTotal(page.getTotal());
        pageVO.setDataList(voList);

        return pageVO;
    }

    @Override
    public void updateGrassLikeNumTask() {

        // 从redis中取头一天的点赞记录
        String yesterday = DateUtil.format(DateUtil.yesterday(), "yyyyMMdd");
        Map<String, Object> cacheMap = redisUtil.getCacheMap("likeNum:" + yesterday);

        // 批处理的次数，比如200个数据，count=2; 230个数据，count=3
        int count = 0;
        int size = cacheMap.size();
        if (size % 100 == 0) {
            count = size / 100;
        } else {
            count = size / 100 + 1;
        }

        // 并发编程中，用于计数
        // 通过该方式，保证所有的更新线程执行完成，删除redis中数据
        CountDownLatch countDownLatch = new CountDownLatch(count);

        // 分批的批量更新
        List<TodayLikeInfoParam> list = new ArrayList<>();
        for (String key : cacheMap.keySet()) {
            TodayLikeInfoParam todayLikeInfoParam = new TodayLikeInfoParam();
            todayLikeInfoParam.setGrassId(Integer.valueOf(key));
            todayLikeInfoParam.setLikeNum((Integer) cacheMap.get(key));
            list.add(todayLikeInfoParam);
            if (list.size() == 100) {
                // 批量更新
                final List<TodayLikeInfoParam> finalList = list;
                threadPoolExecutor.execute(() -> {

                    try {
                        grassMapper.updateBatch(finalList);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    } finally {
                        // countDownLatch计数值-1
                        countDownLatch.countDown();
                    }
                });
                list = new ArrayList<>();
            }
        }
        if (list.size() > 0) {
            // 批量更新
            List<TodayLikeInfoParam> finalList1 = list;
            threadPoolExecutor.execute(() -> {
                try {
                    grassMapper.updateBatch(finalList1);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        try {
            // 阻塞程序的执行，等待countdownlatch的计数减为0
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        redisUtil.deleteObject("likeNum:" + yesterday);
    }
}
